﻿//Sam

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Speech;
using System.Speech.Recognition;
using System.Xml;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using SpeechLib;
using System.Diagnostics;

namespace SpeechRecognitionFull
{
    //Interaction logic for MainWindow.xaml
    public partial class MainWindow : Window
    {
        //initial variables
        SpeechRecognizer speechReco = new SpeechRecognizer();
        Grammar gram;
        List<string> grammarList = new List<string>();
        int numberOfRecognizedWords = 0;

        public MainWindow()
        {
            //initialization methods
            InitializeComponent();
            setupGrammar();

            //required setup variables to enable speech recognition
            //Choices myChoices = new Choices(grammarList.ToArray());
            //GrammarBuilder builder = new GrammarBuilder(myChoices);
            //Grammar gram = new Grammar(builder);

            //load up the speech recognition with the required parameters
            speechReco.LoadGrammar(gram);
            gram.Enabled = true;

            //disable it at first until we want it enabled, in this case when we push the button on the screen, all we need from here though is to set this to enabled to start listening
            speechReco.Enabled = false;

             //This is the key event handler for speech recognition, I moved it down to the button click event handler to show
                //an example of how to establish control over it, but you can put this up here if you want it to immediately start listening
            //speechReco.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(speechReco_SpeechRecognized);

        }


        //listener event handler for when a word in the grammar list is recognized
        void speechReco_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            if (e.Result.Semantics != null)
            {
                if (e.Result.Semantics.ContainsKey("three_digit_first_part"))
                {
                    speechContent.Content += e.Result.Semantics["three_digit_first_part"].Value.ToString();
                    speechContent.Content += e.Result.Semantics["three_digit_second_part"].Value.ToString();
                }
                else if (e.Result.Semantics.ContainsKey("digit"))
                {
                    speechContent.Content += e.Result.Semantics["digit"].Value.ToString();
                }
                else if (e.Result.Semantics.ContainsKey("letter"))
                {
                    speechContent.Content += e.Result.Semantics["letter"].Value.ToString();
                }
                else
                {
                    speechContent.Content += e.Result.Text;
                }
            }
            else
            {
                //and so begins the various special cases of recognized speech
                switch (e.Result.Text)
                {
                    case "left": //the controller will say left, but we want to input just L into the command string
                        speechContent.Content += "L";
                        break;
                    case "right": //the controller will say right, but we want to input just R into the command string
                        speechContent.Content += "R";
                        break;
                    case "dot": //the controller will say dot, but we want to input just period into the command string
                        speechContent.Content += ".";
                        break;
                    default:
                        //add the recognized word (e.Result.Text) to the string of total recognized words and display on the label (speechConent)
                        speechContent.Content += e.Result.Text;
                        break;
                }
            }
        }

        //button click event
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            //basically just toggle between enabled and disabled, resetting the label output in the process

            if (speechReco.Enabled)
            {
                speechReco.Enabled = false;
                speechContent.Content = "Speech Disabled...";
            }
            else
            {
                speechReco.Enabled = true;
                speechReco.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(speechReco_SpeechRecognized); //enable the speech recognition listener
                speechContent.Content = "Speech Enabled, Say Something: ";

            }
        }

        void setupGrammar()
        {
            //read XML file and collect data from there (collects all text not in tags)
            XmlTextReader reader = new XmlTextReader("../../speech.xml");
            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Text: //if it is reading text in the XML document
                        this.grammarList.Add(reader.Value);
                        break;
                }
            } //end reading XML file

            /*
            //add basic digits from 0-9
            for (int i = 0; i < 10; i++)
            {
                this.grammarList.Add(i.ToString());
            }
            
            //add all letters in the alphabet
            for (int alphabetVariable = (int)('A'); alphabetVariable < (int)('Z'); alphabetVariable++)
            {
                this.grammarList.Add(((char)(alphabetVariable)).ToString());
            }
            */

            

            List<SemanticResultValue> phoneticAlphabet = new List<SemanticResultValue>();
            phoneticAlphabet.Add(new SemanticResultValue("alpha", "A"));
            phoneticAlphabet.Add(new SemanticResultValue("bravo", "B"));
            phoneticAlphabet.Add(new SemanticResultValue("charlie", "C"));
            phoneticAlphabet.Add(new SemanticResultValue("delta", "D"));
            phoneticAlphabet.Add(new SemanticResultValue("echo", "E"));
            phoneticAlphabet.Add(new SemanticResultValue("foxtrot", "F"));
            phoneticAlphabet.Add(new SemanticResultValue("golf", "G"));
            phoneticAlphabet.Add(new SemanticResultValue("hotel", "H"));
            phoneticAlphabet.Add(new SemanticResultValue("india", "I"));
            phoneticAlphabet.Add(new SemanticResultValue("juliett", "J"));
            phoneticAlphabet.Add(new SemanticResultValue("kilo", "K"));
            phoneticAlphabet.Add(new SemanticResultValue("lima", "L"));
            phoneticAlphabet.Add(new SemanticResultValue("mike", "M"));
            phoneticAlphabet.Add(new SemanticResultValue("november", "N"));
            phoneticAlphabet.Add(new SemanticResultValue("oscar", "O"));
            phoneticAlphabet.Add(new SemanticResultValue("papa", "P"));
            phoneticAlphabet.Add(new SemanticResultValue("quebec", "Q"));
            phoneticAlphabet.Add(new SemanticResultValue("romeo", "R"));
            phoneticAlphabet.Add(new SemanticResultValue("sierra", "S"));
            phoneticAlphabet.Add(new SemanticResultValue("tango", "T"));
            phoneticAlphabet.Add(new SemanticResultValue("uniform", "U"));
            phoneticAlphabet.Add(new SemanticResultValue("victor", "V"));
            phoneticAlphabet.Add(new SemanticResultValue("whiskey", "W"));
            phoneticAlphabet.Add(new SemanticResultValue("ex ray", "X"));
            phoneticAlphabet.Add(new SemanticResultValue("yankee", "Y"));
            phoneticAlphabet.Add(new SemanticResultValue("zulu", "Z"));

            Choices letters = new Choices();
            GrammarBuilder letterValues = new GrammarBuilder();
            foreach (SemanticResultValue letter in phoneticAlphabet)
            {
                letters.Add(letter);
                letterValues.Append(letter);
            }
            GrammarBuilder phoneticAlphabetGrammar = new GrammarBuilder(new SemanticResultKey("letter", letters));

            // Numbers
            Choices digits = new Choices();
            GrammarBuilder digitValues = new GrammarBuilder();

            List<SemanticResultValue> digitList = new List<SemanticResultValue>();
            digitList.Add(new SemanticResultValue("zero", 0));
            digitList.Add(new SemanticResultValue("one", 1));
            digitList.Add(new SemanticResultValue("two", 2));
            digitList.Add(new SemanticResultValue("three", 3));
            digitList.Add(new SemanticResultValue("four", 4));
            digitList.Add(new SemanticResultValue("five", 5));
            digitList.Add(new SemanticResultValue("six", 6));
            digitList.Add(new SemanticResultValue("seven", 7));
            digitList.Add(new SemanticResultValue("eight", 8));
            digitList.Add(new SemanticResultValue("niner", 9));

            foreach (SemanticResultValue digit in digitList)
            {
                digits.Add(digit);
                digitValues.Append(digit);
            }
            GrammarBuilder digitGrammar = new GrammarBuilder(new SemanticResultKey("digit", digits));

            // 10-19
            List<string> teensList = new List<string>();
            for (int i = 10; i < 20; i++)
            {
                teensList.Add(i.ToString());
            }
            Choices teens = new Choices(teensList.ToArray());
            GrammarBuilder teensGrammar = new GrammarBuilder(teens);

            // 20-99
            List<string> twentyAndAboveList = new List<string>();
            for (int i = 20; i < 100; i++)
            {
                twentyAndAboveList.Add(i.ToString());
            }
            Choices twentyAndAbove = new Choices(twentyAndAboveList.ToArray());
            GrammarBuilder twentyAndAboveGrammar = new GrammarBuilder(twentyAndAbove);

            // Two-digit number
            Choices twoDigit = new Choices(teensGrammar, twentyAndAboveGrammar);
            GrammarBuilder twoDigitGrammar = new GrammarBuilder(twoDigit);

            // Three-digit number
            GrammarBuilder threeDigitGrammar = new GrammarBuilder();
            threeDigitGrammar.Append(new SemanticResultKey("three_digit_first_part", digitGrammar));
            threeDigitGrammar.Append(new SemanticResultKey("three_digit_second_part", twoDigitGrammar));
            
            Choices number = new Choices(digitGrammar, twoDigitGrammar, threeDigitGrammar);
            GrammarBuilder numberGrammar = new GrammarBuilder(number);

            List<string> airlinesList = new List<string>();
            airlinesList.Add("Alaska");
            airlinesList.Add("American");
            airlinesList.Add("Continental");
            airlinesList.Add("Southwest");
            airlinesList.Add("United");
            airlinesList.Add("Virgin America");
            Choices airlines = new Choices(airlinesList.ToArray());
            GrammarBuilder airlinesGrammar = new GrammarBuilder(airlines);

            // Grammar to recognize a Flight as airline plus flight number
            GrammarBuilder flightGrammar = new GrammarBuilder();
            flightGrammar.Append(airlinesGrammar);
            flightGrammar.Append(numberGrammar);
            
            // Grammar to recognize cleared for takeoff command
            GrammarBuilder clearForTakeoffGrammar = new GrammarBuilder();
            clearForTakeoffGrammar.Append(flightGrammar);
            clearForTakeoffGrammar.Append("cleared for take off");

            Choices allChoices = new Choices(phoneticAlphabetGrammar, clearForTakeoffGrammar);
            GrammarBuilder allGrammar = new GrammarBuilder(allChoices);

            gram = new Grammar(allGrammar);
        }
    }
}
